﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Jzy.Workflow.Line;
using Jzy.Workflow.Snap;
using System.Xml.Linq;
using Frame.Lib.Core.Role;
using Frame.Lib.Utilities;

namespace Jzy.Workflow.Node
{
    public partial class FlowNodeInfo
    {
        

        public FlowNodeInfo()
        {
            this.Width = 90f;
            this.Height = 55f;
            this.RoleNames = "";
            this.UserNames = "";
            GetNextInfos = id => null;
            GetUserIDs = id => null;
            GetAllUserIDs = GetRoleIDs = id => null;
        }

        public FlowNodeInfo(XElement nodes, XElement lines, XElement nodeRoles, XElement nodeUsers, int nodeID):this()
        {
            this.InitNode(nodes, lines, nodeRoles, nodeUsers, nodeID);            
        }

        private void InitNode(XElement nodes, XElement lines, XElement nodeRoles, XElement nodeUsers, int nodeID)
        {
            _xmlNodes = nodes;
            _xmlNodeRoles = nodeRoles;
            _xmlNodeUsers = nodeUsers;
            _xmlLines = lines;

            XElement node = _xmlNodes.Elements().Where(T => T.Element("ID").Value == nodeID.ToString()).First();

            this.ID = nodeID;
            this.Name = node.Element("Name").Value;
            this.FlowID = int.Parse(node.Element("FlowID").Value);
            this.TypeID = int.Parse(node.Element("TypeID").Value);
            this.Left = double.Parse(node.Element("Left").Value);
            this.Top = double.Parse(node.Element("Top").Value);
            this.Width = double.Parse(node.Element("Width").Value);
            this.Height = double.Parse(node.Element("Height").Value);
            this.RoleNames = node.Element("RoleNames").Value;
            this.UserNames = node.Element("UserNames").Value;
            this.AllowAdd = bool.Parse(node.Element("AllowAdd").Value);
            this.AllowBack = bool.Parse(node.Element("AllowBack").Value);
            this.AllowPass = bool.Parse(node.Element("AllowPass").Value);
            this.AllowJump = bool.Parse(node.Element("AllowJump").Value);
            this.SubmitMode = int.Parse(node.Element("SubmitMode").Value);
            this.IsParallel = bool.Parse(node.Element("IsParallel").Value);
            this.ParallelMode = int.Parse(node.Element("ParallelMode").Value);
            if (node.Element("DefaultUserID").Value != "")
            {
                this.DefaultUserID = int.Parse(node.Element("DefaultUserID").Value);
            }
            this.DefaultNextNodeID = int.Parse(node.Element("DefaultNextNodeID").Value);

            //取出所有的用户ID，包括角色的

            List<int> roleIDs = _xmlNodeRoles.Elements().Where(ele => ele.Element("NodeID").Value == this.ID.ToString()).Select(ele => int.Parse(ele.Element("RoleID").Value)).ToList();
            List<int> userIDs = _xmlNodeUsers.Elements().Where(ele => ele.Element("NodeID").Value == this.ID.ToString()).Select(ele => int.Parse(ele.Element("UserID").Value)).ToList();
            RoleBO role = new RoleBO();
            CommUtil.MergeList<int>(userIDs, role.GetUserIDs(roleIDs));
            this.AllUserIDs = userIDs;
        }

        public FlowNodeInfo(FlowSnapInfo snap, int nodeID):this()
        {
            this.InitNode(XElement.Parse(snap.Nodes), XElement.Parse(snap.Lines), XElement.Parse(snap.NodeRoles), XElement.Parse(snap.NodeUsers), nodeID);
        }


        public Func<object, List<FlowNodeInfo>> GetNextInfos;
        private List<FlowNodeInfo> _nextNodes;
        public List<FlowNodeInfo> NextNodes
        {
            get
            {
                if (_nextNodes == null)
                {
                    if (_xmlNodes == null)
                    {
                        _nextNodes = GetNextInfos(this.ID);
                    }
                    else
                    {
                        _nextNodes = GetNextInfosByXml();
                    }
                }
                return _nextNodes;
            }
            set
            {
                _nextNodes = value;
            }
        }
       

        public Func<object, List<int>> GetUserIDs
        {
            get;
            set;
        }
        private List<int> _userIDs;
        public List<int> UserIDs
        {
            get
            {
                if (_userIDs == null)
                {
                    if (_xmlNodes == null)
                    {
                        _userIDs = GetUserIDs(ID);
                    }
                    else
                    {
                        _userIDs = GetUserIDsByXml();
                    }
                }
                return _userIDs;
            }
            set
            {
                _userIDs = value;
            }
        }    
       

        public Func<object, List<int>> GetAllUserIDs
        {
            get;
            set;
        }
        private List<int> _allUserIDs;
        /// <summary>
        /// 这个节点的所有用户ID，包括角色里的用户
        /// </summary>
        public List<int> AllUserIDs
        {
            get
            {
                if (_allUserIDs == null)
                {
                    _allUserIDs = GetAllUserIDs(ID);
                }
                return _allUserIDs;
            }
            set
            {
                _allUserIDs = value;
            }
        }

        public Func<object, List<int>> GetRoleIDs;
        private List<int> _roleIDs;
        public List<int> RoleIDs
        {
            get
            {
                if (_roleIDs == null)
                {
                    if (_xmlNodes == null)
                    {
                        _roleIDs = GetRoleIDs(ID);
                    }
                    else
                    {
                        _roleIDs = GetRoleIDsByXml();
                    }
                }
                return _roleIDs;
            }
            set
            {
                _roleIDs = value;
            }
        }

       
        

        public Func<int, List<FlowLineInfo>> GetFromLines;
        private List<FlowLineInfo> _fromLines;
        /// <summary>
        /// 从此节点出发的路由
        /// </summary>
        public List<FlowLineInfo> FromLines
        {
            get
            {
                if (_fromLines == null)
                {
                    if (_xmlNodes == null)
                    {
                        _fromLines = GetFromLines(this.ID);
                    }
                    else
                    {
                        _fromLines = GetFromLinesByXml();
                    }
                }
                return _fromLines;
            }
            set
            {
                _fromLines = value;
            }
        }

      

        public Func<int, List<FlowLineInfo>> GetToLines;
        private List<FlowLineInfo> _toLines;
        /// <summary>
        /// 到此节点的路由
        /// </summary>
        public List<FlowLineInfo> ToLines
        {
            get
            {
                if (_toLines == null)
                {
                    if (_xmlNodes == null)
                    {
                        _toLines = GetToLines(this.ID);
                    }
                    else
                    {
                        _toLines = GetToLinesByXml();
                    }
                }
                return _toLines;
            }
            set
            {
                _toLines = value;
            }
        }

       

        #region 针对XML的所有操作

        private XElement _xmlLines;
        private XElement _xmlNodes;
        private XElement _xmlNodeRoles;
        private XElement _xmlNodeUsers;

        
        private List<FlowLineInfo> GetFromLinesByXml()
        {
            IEnumerable<XElement> lines = _xmlLines.Elements().Where(ele => ele.Element("FromNodeID").Value == this.ID.ToString());

            List<FlowLineInfo> lst = new List<FlowLineInfo>();

            foreach (XElement ele in lines)
            {
                lst.Add(ParseLine(ele));
            }

            return lst;
        }

        private FlowLineInfo ParseLine(XElement line)
        {
            FlowLineInfo info = new FlowLineInfo();

            info.ID = int.Parse(line.Element("ID").Value);
            info.Name = line.Element("Name").Value;
            info.FlowID = int.Parse(line.Element("FlowID").Value);
            info.TypeID = int.Parse(line.Element("TypeID").Value);
            info.FromNodeID = int.Parse(line.Element("FromNodeID").Value);
            info.ToNodeID = int.Parse(line.Element("ToNodeID").Value);
            info.Rules = line.Element("Rules").ToString();

            return info;
        }

        private List<FlowLineInfo> GetToLinesByXml()
        {
            IEnumerable<XElement> lines = _xmlLines.Elements().Where(ele => ele.Element("ToNodeID").Value == this.ID.ToString());

            List<FlowLineInfo> lst = new List<FlowLineInfo>();

            foreach (XElement ele in lines)
            {
                lst.Add(ParseLine(ele));
            }

            return lst;
        }

        private List<FlowNodeInfo> GetNextInfosByXml()
        {
            IEnumerable<int> nextNodeIDs = from node in _xmlNodes.Elements()
                                           where
                                           (
                                                 from line in _xmlLines.Elements()
                                                 where line.Element("FromNodeID").Value == this.ID.ToString()
                                                 select line.Element("ToNodeID").Value
                                            ).Contains(node.Element("ID").Value)
                                           select int.Parse(node.Element("ID").Value);
            List<FlowNodeInfo> lstNodes = new List<FlowNodeInfo>();
            foreach (int id in nextNodeIDs)
            {
                lstNodes.Add(new FlowNodeInfo(_xmlNodes, _xmlLines, _xmlNodeRoles, _xmlNodeUsers, id));
            }

            return lstNodes;
        }

       
        private List<int> GetRoleIDsByXml()
        {
            IEnumerable<int> roleIDs = _xmlNodeRoles.Elements().Where(ele => ele.Element("NodeID").Value == this.ID.ToString()).Select(ele => int.Parse(ele.Element("RoleID").Value));
            return roleIDs.ToList();
        }
        private List<int> GetUserIDsByXml()
        {
            IEnumerable<int> userIDs = _xmlNodeUsers.Elements().Where(ele => ele.Element("NodeID").Value == this.ID.ToString()).Select(ele => int.Parse(ele.Element("UserID").Value));
            return userIDs.ToList();
        }

        #endregion


    }
}
